package com.openbravo.pos.base;

import java.lang.reflect.Constructor;
import java.util.HashMap;

import cn.ekuma.rabbit.ModelManager;
import cn.ekuma.rabbit.spi.I_Model;
import cn.ekuma.rabbit.spi.I_ModelPart;
import cn.ekuma.security.I_SecurityManager;
import cn.ekuma.security.I_SecurityObject;

public class BeanFactoryManager {
	HashMap<String, String> m_oldclasses = new HashMap<String, String>();
	
	HashMap<String, BeanFactory> m_aBeanFactories = new HashMap<String, BeanFactory>();

	I_AppView app;
	ModelManager manager;

	 public BeanFactoryManager(I_AppView app,
			 ModelManager manager ) {
		 this.app=app;
		 this.manager=manager;
	}

	public Object getBean(String beanfactory) throws BeanFactoryException {

	        // For backwards compatibility
	        beanfactory = mapNewClass(beanfactory);


	        BeanFactory bf = m_aBeanFactories.get(beanfactory);
	        if (bf == null) {
	            // testing sripts
	            if (beanfactory.startsWith("/")) {
	                bf = new BeanFactoryScript(beanfactory);
	            } else {
	                // Class BeanFactory
	                try {
	                    Class bfclass = Class.forName(beanfactory);
	                    if (BeanFactory.class.isAssignableFrom(bfclass)) {
	                        bf = (BeanFactory) bfclass.newInstance();
	                    } else {
	                        // the old construction for beans...
	                        Constructor constMyView = bfclass.getConstructor(new Class[] {I_AppView.class});
	                        Object bean = constMyView.newInstance(new Object[] {app});

	                        bf = new BeanFactoryObj(bean);
	                    } 
	                } catch (Exception e) {
	                    // ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException
	                    throw new BeanFactoryException(e);
	                }
	            }
	           
	            // cache the factory
	            m_aBeanFactories.put(beanfactory, bf); 
	            
	            if(bf instanceof I_ModelPart){
            		I_ModelPart modelPart=(I_ModelPart)bf;
            		I_Model mode=manager.getModelByName(modelPart.getModelName());
            		modelPart.setModel(mode);
            		if(bf instanceof I_SecurityObject){
            			I_SecurityObject securityObject=(I_SecurityObject)bf;
            			I_SecurityManager securityManager=mode.getModelSecurityManager();
            			if(securityManager!=null)
            				securityManager.fillSecurityObject(securityObject);
            		}
	            }
	            
	            // Initialize if it is a BeanFactoryApp
	            if (bf instanceof BeanFactoryApp) {
	                ((BeanFactoryApp) bf).init(app);
	            }
	        }
	        Object bean=bf.getBean();
	        if(bf!=bean&&bean instanceof I_ModelPart){
            		I_ModelPart modelPart=(I_ModelPart)bean;
            		I_Model mode=manager.getModelByName(modelPart.getModelName());
            		modelPart.setModel(mode);
            		if(bf instanceof I_SecurityObject){
            			I_SecurityObject securityObject=(I_SecurityObject)bf;
            			I_SecurityManager securityManager=mode.getModelSecurityManager();
            			if(securityManager!=null)
            				securityManager.fillSecurityObject(securityObject);
            		}
            }
	        return bean;
	    }
	 
	 protected  String mapNewClass(String classname) {
	        String newclass = m_oldclasses.get(classname);
	        return newclass == null
	                ? classname
	                : newclass;
	    }
}
